/**
 * File.c, implimentation of the File object.
 *
 * Version 1.1
 *
 * Version History:
 * 1.0	Last copy after completion of HW1 in the HW1 project.
 * 1.1  Updated to use new Object_method convention.
 */

#include "../../gc6.7/include/gc.h"

#include "File.h" // comment out if no .h file
// create one if needed

#include <assert.h>


/*-----------------------------------------------*/
pFile File_new(const pString filename, const pString fileOptions)
{
	assert(filename);
	assert(fileOptions);

	pFile ret = GC_malloc(sizeof(File));
	assert(ret);
	ret->filename = String_clone(filename);
	ret->options = String_clone(fileOptions);
	ret->fileHandle = fopen(ret->filename->cString, ret->options->cString);
	assert(ret->fileHandle);
	return ret;
}


/*-----------------------------------------------*/
pFile File_Create(const char* filename, const char* contents)
{
	pFile file = File_new(String_new(filename), String_new("w+"));
	int errorCode = File_Write(file, String_new(contents));
	assert(errorCode != 0);
	return file;
}


/*-----------------------------------------------*/
pString File_Read(pFile file)
{
	pString ret = String_new(NULL);
	ret = String_resize(ret, 4096);
	int bytesRead = fread(ret->cString, sizeof(char), ret->length, file->fileHandle);
	fseek(file->fileHandle, 0, SEEK_SET);
	return ret;
}


/*-----------------------------------------------*/
pString File_readAll(pFile file)
{
	pString ret = String_new(NULL);
	int fileSize = File_getSize(file);
	ret = String_resize(ret, fileSize + 10);
	fseek(file->fileHandle, 0, SEEK_SET);
	int bytesRead = fread(ret->cString, sizeof(char), ret->length, file->fileHandle);
	fseek(file->fileHandle, 0, SEEK_SET);
	return ret;
}


/*-----------------------------------------------*/
int File_Write(pFile file, pString contents)
{
	assert(file);
	assert(contents);
	if (String_indexOf(file->options, "w") == -1 && !String_equals(contents, String_new("r+")))
	{
		return 0;
	}
	int ret = fwrite(contents->cString, sizeof(char), contents->length, file->fileHandle);
	return ret != 0;
}


/*-----------------------------------------------*/
int File_Append(pFile file, pString toAppend)
{
	assert(file);
	assert(toAppend);
	if (String_indexOf(file->options, "a") == -1)
	{
		return 0;
	}
	int ret = fwrite(toAppend->cString, sizeof(char), toAppend->length, file->fileHandle);
	return ret != 0;
}


/*-----------------------------------------------*/
int File_Empty(pFile pInputFile)
{
	File_Close(pInputFile);
	pString originalOptions = pInputFile->options;
	pString filename = pInputFile->filename;
	FILE* file = fopen(filename->cString, "w+"); // erases origional contents
	fclose(file);
	pInputFile->fileHandle = fopen(filename->cString, originalOptions->cString);
	assert(pInputFile->fileHandle != NULL);
}


/*-----------------------------------------------*/
int File_getSize(pFile file)
{
	assert(file);
	pString origionalOptions = file->options;
	pString filename = file->filename;
	File_Close(file);
	file = File_new(file->filename, String_new("r"));
	pString ret = String_new(NULL);
	ret = String_resize(ret, 4096);
	assert(file->fileHandle);
	int bytesRead = fread(ret->cString, sizeof(char), ret->length, file->fileHandle);

	fseek(file->fileHandle, 0, SEEK_SET);
	return bytesRead;
}


/*-----------------------------------------------*/
int File_Close(pFile file)
{
	assert(file != NULL);

	return fclose(file->fileHandle) == 0;
}


/*-----------------------------------------------*/
int File_Delete(pFile file)
{
	assert(file != NULL);
	assert(file->filename != NULL);

	File_Close(file);
	return remove(file->filename->cString) == 0;
}
